﻿using FluentValidation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace IdentityWebApi.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class TestController : ControllerBase
    {
        private readonly ILogger<TestController> _logger;
        private readonly RoleManager<Role> _roleManager;
        private readonly UserManager<User> _userManager;
        private readonly IValidator<User> _validator;

        public TestController(ILogger<TestController> logger, RoleManager<Role> roleManager, UserManager<User> userManager, IValidator<User> validator)
        {
            _logger = logger;
            _roleManager = roleManager;
            _userManager = userManager;
            _validator = validator;
        }

        /// <summary>
        /// 创建用户
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> CreateUser()
        {
            bool roleExists = await _roleManager.RoleExistsAsync("admin");
            if (!roleExists)
            {
                Role role = new Role { Name = "admin" };
                var r = await _roleManager.CreateAsync(role);
                if (!r.Succeeded)
                {
                    return BadRequest(r.Errors);
                }
            }
            User user = await _userManager.FindByNameAsync("wja2");
            if (user == null)
            {
                user = new User { UserName = "wja2", Email = "1258399119@qq.com", EmailConfirmed = true };
                var r = await _userManager.CreateAsync(user, "123456");
                if (!r.Succeeded)
                {
                    return BadRequest(r.Errors);
                }
                r = await _userManager.AddToRoleAsync(user, "admin");
                if (!r.Succeeded)
                {
                    return BadRequest(r.Errors);
                }
            }
            return Ok();
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> Login(string userName, string password)
        {
            var user = await _userManager.FindByNameAsync(userName);
            if (user == null)
            {
                return NotFound($"用户名不存在{userName}");
            }
            if (await _userManager.IsLockedOutAsync(user))
                return BadRequest("LockedOut");
            var success = await _userManager.CheckPasswordAsync(user, password);
            if (success) return Ok("Success");
            else await _userManager.AccessFailedAsync(user);
            return BadRequest("登录失败");
        }

        /// <summary>
        /// 重置密码令牌
        /// </summary>
        /// <param name="email"></param>
        /// <returns></returns>
        [HttpPost("SendResetPasswordToken")]
        public async Task<IActionResult> SendResetPasswordToken(string email)
        {
            var user = await _userManager.FindByEmailAsync(email);
            if (user == null) return NotFound("为查找到该邮箱对于的用户");
            string token = await _userManager.GeneratePasswordResetTokenAsync(user);
            _logger.LogInformation($"向邮箱：{user.Email}发送Token={token}");
            return Ok("重置令牌已发送到指定的邮箱");
        }

        /// <summary>
        /// 重置密码成功
        /// </summary>
        /// <param name="email"></param>
        /// <param name="password"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpPost("VerifyResetPasswordToken")]
        public async Task<IActionResult> VerifyResetPasswordToken(string email, string password, string token)
        {
            var user = await _userManager.FindByEmailAsync(email);
            if (user == null) return NotFound("为找到用户");
            var res = await _userManager.ResetPasswordAsync(user, password, token);
            if (res.Succeeded) return Ok("重置密码成功");
            return BadRequest("重置密码失败");
        }

        /// <summary>
        /// 生成 jwt
        /// </summary>
        /// <returns></returns>
        [HttpGet("GetJwtToken")]
        public IActionResult GetJwtToken()
        {
            var jwt = new JwtHelper();
            var token = jwt.GenerateJwt();
            return Ok(token);
        }
        /// <summary>
        /// 解析 jwt
        /// </summary>
        /// <returns></returns>
        [HttpGet("DCodeJwtToken")]
        public IActionResult DCodeJwtToken(string jwt)
        {
            var jwtHelper = new JwtHelper();
            jwtHelper.DecryptJwt(jwt);
            return Ok();
        }

        /// <summary>
        /// 解析 jwt
        /// </summary>
        /// <returns></returns>
        [HttpGet("DCodeJwtToken2")]
        public IActionResult DCodeJwtToken2(string jwt)
        {
            var jwtHelper = new JwtHelper();
            jwtHelper.Decrypt(jwt);
            return Ok();
        }

        /// <summary>
        /// 登录2
        /// </summary>
        /// <returns></returns>
        [HttpPost("Login2")]
        public async Task<IActionResult> Login2(string userName, string password, [FromServices] IOptions<JwtOptions> jwtOptions)
        {
            var user = await _userManager.FindByNameAsync(userName);
            if (user == null) return NotFound(userName);
            var success = await _userManager.CheckPasswordAsync(user, password);
            if (!success)
            {
                return BadRequest("Failed");
            }
            // 每一次登录都需要让版本加一
            user.JwtVersion++;
            await _userManager.UpdateAsync(user);

            var claims = new List<Claim>();
            claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()));
            claims.Add(new Claim(ClaimTypes.Name, user.UserName));
            claims.Add(new Claim(ClaimTypes.Version, user.JwtVersion.ToString()));

            var roles = await _userManager.GetRolesAsync(user);
            foreach (var role in roles)
            {
                claims.Add(new Claim(ClaimTypes.Role, role));
            }
            string jwtToken = BuildToken(claims, jwtOptions.Value);
            return Ok(jwtToken);
        }

        private static string BuildToken(IEnumerable<Claim> claims, JwtOptions options)
        {
            DateTime expires = DateTime.Now.AddSeconds(options.ExpireSeconds);
            byte[] keyBytes = Encoding.UTF8.GetBytes(options.SigningKey);
            var seckey = new SymmetricSecurityKey(keyBytes);
            var credentials = new SigningCredentials(seckey, SecurityAlgorithms.HmacSha256Signature);
            var tokenDescriptor = new JwtSecurityToken(expires: expires, signingCredentials: credentials, claims: claims);
            return new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);
        }

        /// <summary>
        /// 在控制器中使用 FluentValidation
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task DoSomething(User user)
        {
            var validationResult = await _validator.ValidateAsync(user);
            if (!validationResult.IsValid)
            {
                foreach (var error in validationResult.Errors)
                {
                    _logger.LogError(error.ErrorMessage);
                }
            }
            else
            {
                // 进行其他操作
                _logger.LogInformation("用户验证成功");
            }
        }

        
    }
}